#include "Thread.h"
#include "../tools/ShareApi.h"
#include "../stream/StringTools.h"
#include "SharedPtr.h"
DEF_BEG_LIBTOOLS

CThread::ThreadData::ThreadData()
{
	_func = NullPtr;
	_arg = NullPtr;
	_hThread = 0;
	_dwRet = 0;
	_id = 0;
	_bRun = false;
	_detach = false;
}

CThread::CThread()
{
	_data = new CThread::ThreadData();
}

CThread::~CThread()
{
	if (_data) delete _data;
	_data = NullPtr;
}

CThread::CThread(const one_function<DWORD, void *>& func, void* arg/* = NullPtr */)
{
	_data = new CThread::ThreadData();

	_data->_func = func;
	_data->_arg = arg;
	_data->_dwRet = 0;
	_data->_id = 0;
	_data->_bRun = false;

	_data->_hThread = ShareApi::BeginThread(&ThreadFunc, _data, 0, &_data->_id);
	if (!_data->_hThread)
	{
		SharedPtr<TCHAR> ec(ShareApi::Global_GetLastError(), &ShareApi::Global_FreeMem);
		throw CThreadException(TO_STRING(ec.Get()).c_str());
	}
	else _data->_bRun = true;
}

DWORD CThread::ThreadFunc(void *arg)
{
	CThread::ThreadData* data = (CThread::ThreadData*)arg;
	if (!(data->_func))
	{
		throw CThreadException("thread function is null");
	}

	data->_dwRet = data->_func(data->_arg);

	data->_bRun = false;
	DWORD dwRet = data->_dwRet;

	if (data->_detach) {
		delete data;
	}

	return dwRet;
}

ULONG CThread::Id()
{
	return _data->_id;
}

DWORD CThread::GetRet()
{
	return _data->_dwRet;
}

bool CThread::IsRun()
{
	return _data->_bRun;
}

DWORD CThread::Join()
{
	ShareApi::Thread_Join(_data->_hThread);
	return _data->_dwRet;
}

void CThread::Detach()
{
	CThread::ThreadData *data = new CThread::ThreadData();
	_data->_detach = true;
	ShareApi::CloseThread(_data->_hThread);
	_data->_hThread = 0;
	std::swap(data, _data);
}

bool CThread::Start(const one_function<DWORD, void *>& func, void* arg)
{
	_data->_func = func;
	_data->_arg = arg;
	_data->_hThread = ShareApi::BeginThread(&ThreadFunc, this, 0, &_data->_id);
	if (!_data->_hThread) _data->_bRun = false;
	else _data->_bRun = true;

	return _data->_bRun;
}

DEF_END_LIBTOOLS